package com.wang.tool.lock.aop;

import com.wang.tool.cache.aop.Cache;
import com.wang.tool.cache.aop.CacheAdvice;
import com.wang.tool.cache.aop.CacheKeyBuilder;
import com.wang.tool.cache.aop.CacheRemove;
import com.wang.tool.cache.core.CacheInstance;
import com.wang.tool.lock.LockServer;
import com.wang.tool.util.CommonUtil;
import com.wang.tool.util.SimpleLogUtil;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author wangshaopeng
 * @Date 2022/5/10
 */
public class LockConfiguration {

    @Bean("lockAdvisor1")
    @ConditionalOnMissingBean(name = "lockAdvisor1")
    public Advisor lockAdvisor1(@Autowired LockAdvisorOrder order, @Autowired LockServer lockServer, @Autowired LockKeyBuilder keyBuilder) {
        LockAdvice cacheAdvice = new LockAdvice(lockServer,keyBuilder);
        Advice advice = (MethodInterceptor) invocation -> cacheAdvice.lockAround(new MethodInvocationProceedingJoinPoint((ProxyMethodInvocation) invocation));
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        String expression =
                //方法/类注解
                "@annotation(" + Lock.class.getName() + ")"
                        //public
                        + " && execution(public * *(..))"
                        //非Object自带函数
                        + " && !execution(public java.lang.String toString())"
                        + " && !execution(public int hashCode())"
                        + " && !execution(public boolean equals(java.lang.Object))";
        advisor.setExpression(expression);
        advisor.setOrder(order.getOrder());
        advisor.setAdvice(advice);
        SimpleLogUtil.info("[{0}IsAvailable] order:{1}, expression:{2}", Lock.class.getName(), order.getOrder(), expression);
        return advisor;
    }

}
